// This function works with or without 'new': a constructor and factory function
function Range(from, to) {
    // These are descriptors for the read-only from and to properties.
    var props = {
        from: {value: from, enumerable: true, writable: false, configurable: false},
        to: {value: to, enumerable: true, writable: false, configurable: false}
    };

    if (this instanceof Range)                // If invoked as a constructor
        Object.defineProperties(this, props); // Define the properties
    else                                      // Otherwise, as a factory 
        return Object.create(Range.prototype, // Create and return a new
            props);          // Range object with props
}

// If we add properties to the Range.prototype object in the same way,
// then we can set attributes on those properties.  Since we don't specify
// enumerable, writable, or configurable, they all default to false.
Object.defineProperties(Range.prototype, {
    includes: {
        value: function (x) {
            return this.from <= x && x <= this.to;
        }
    },
    foreach: {
        value: function (f) {
            for (var x = Math.ceil(this.from); x <= this.to; x++) f(x);
        }
    },
    toString: {
        value: function () {
            return "(" + this.from + "..." + this.to + ")";
        }
    }
});
